﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Diagnostics;

namespace GDA.Provider.MySql
{
    /// <summary>
    /// Representa um utilitarios para backup.
    /// </summary>
    public class BackupUtility
    {
        #region Variáveis Locais

        private string _username;

        private string _password;

        private string _host;

        private int _port = 3306;

        private string _defaultCharacterSet = "utf8";

        private string _database;

        private bool _exportXML = false;

        private string _destinationFile;

        private string _mysqlDumpPath;

        private string _mysqlPath;

        #endregion

        #region Propriedades

        /// <summary>
        /// Usuário de acesso.
        /// </summary>
        public string Username
        {
            get { return _username; }
            set 
            {
                if (string.IsNullOrEmpty(value))
                    throw new ArgumentNullException("Username");

                _username = value; 
            }
        }

        /// <summary>
        /// Senha de acesso.
        /// </summary>
        public string Password
        {
            get { return _password; }
            set 
            {
                if (string.IsNullOrEmpty(value))
                    throw new ArgumentNullException("Password");

                _password = value; 
            }
        }

        /// <summary>
        /// Host do banco de dados.
        /// </summary>
        public string Host
        {
            get { return _host; }
            set 
            {
                if (string.IsNullOrEmpty(value))
                    throw new ArgumentNullException("Host");

                _host = value; 
            }
        }

        /// <summary>
        /// Porta de comunicação.
        /// </summary>
        public int Port
        {
            get { return _port; }
            set { _port = value; }
        }

        public string DefaultCharacterSet
        {
            get { return _defaultCharacterSet; }
            set { _defaultCharacterSet = value; }
        }

        /// <summary>
        /// Base de dados que será importada ou exportada.
        /// </summary>
        public string Database
        {
            get { return _database; }
            set 
            {
                if (string.IsNullOrEmpty(value))
                    throw new ArgumentNullException("Database");

                _database = value; 
            }
        }

        /// <summary>
        /// Identifica se será usado o formato XML.
        /// </summary>
        public bool ExportXML
        {
            get { return _exportXML; }
            set { _exportXML = value; }
        }

        /// <summary>
        /// Nome do arquivo de importação ou exportação.
        /// </summary>
        public string DestinationFile
        {
            get { return _destinationFile; }
            set 
            {
                if (string.IsNullOrEmpty(value))
                    throw new ArgumentNullException("DestinationFile");

                _destinationFile = value; 
            }
        }

        /// <summary>
        /// Caminho do Mysqldump.
        /// </summary>
        public string MysqlDumpPath
        {
            get { return _mysqlDumpPath; }
            set { _mysqlDumpPath = value; }
        }

        /// <summary>
        /// Caminho do programa Mysql para importação dos dados.
        /// </summary>
        public string MysqlPath
        {
            get { return _mysqlPath; }
            set { _mysqlPath = value; }
        }

        #endregion

        #region Construtores

        /// <summary>
        /// 
        /// </summary>
        /// <param name="host">Nome do host onde está o banco de dados.</param>
        /// <param name="username">Usuário de acesso ao banco de dados.</param>
        /// <param name="password">Senha de acesso.</param>
        /// <param name="database">Nome da base de dados.</param>
        /// <param name="destinationFile">Arquivo de destino dos dados importados ou exportados.</param>
        public BackupUtility(string host, string username, string password, string database, string destinationFile)
        {
            Host = host;
            Username = username;
            Password = password;
            Database = database;
            DestinationFile = destinationFile;
        }

        #endregion

        #region Métodos Públicos

        /// <summary>
        /// Exporta os dados.
        /// </summary>
        public void Export()
        {
            if (string.IsNullOrEmpty(_mysqlDumpPath))
                throw new Exception("MysqlDump not defined.");

            else if (!System.IO.File.Exists(_mysqlDumpPath))
                throw new Exception(string.Format("MysqlDump file \"{0}\" not exists.", _mysqlDumpPath));

            Exception exceptionOcurred = null;

            // Define o delegate que será acionado quando ocorrer algum
            // erro no execução do comando
            DataReceivedEventHandler dataError = new
            DataReceivedEventHandler(delegate(object sender, DataReceivedEventArgs e)
            {
                if (!string.IsNullOrEmpty(e.Data))
                    exceptionOcurred = new Exception(e.Data);
            });

            Process p1 = new Process();

            // Prepara os argumentos do comando
            string cmdArgs = "/c " + (_mysqlDumpPath.IndexOf(' ') >= 0 ? "\"" + _mysqlDumpPath + "\"" : _mysqlDumpPath) + " ";

            cmdArgs += "-u " + _username + " -p" + _password + " -h " + _host + 
                   " --default-character-set=" + _defaultCharacterSet + 
                   " -P " +  _port.ToString() + " -x -e" + 
                   (!string.IsNullOrEmpty(_database) ? " -B " + _database : "") + " > " +
                   (_destinationFile.IndexOf(' ') >= 0 ? "\"" + _destinationFile + "\"" : _destinationFile);

            p1.StartInfo = new ProcessStartInfo(@"cmd", cmdArgs);

            p1.EnableRaisingEvents = false;

            p1.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
            p1.StartInfo.CreateNoWindow = true;
            p1.StartInfo.RedirectStandardError = true;
            p1.StartInfo.UseShellExecute = false;

            p1.ErrorDataReceived += dataError;
            p1.Start();

            // Inicializa a leitura dos dados de erro ocorridos
            p1.BeginErrorReadLine();

            // Espera o programa ser finalizado
            p1.WaitForExit();

            p1.ErrorDataReceived -= dataError;

            // Verifica se ocorreu algum erro
            if (exceptionOcurred != null)
                throw exceptionOcurred;
        }

         /// <summary>
        /// Importa os dados.
        /// </summary>
        public void Import()
        {
            if (string.IsNullOrEmpty(_mysqlPath))
                throw new Exception("Mysql not defined.");

            else if (!System.IO.File.Exists(_mysqlPath))
                throw new Exception(string.Format("Mysql file \"{0}\" not exists.", _mysqlPath));

            Exception exceptionOcurred = null;

            // Define o delegate que será acionado quando ocorrer algum
            // erro no execução do comando
            DataReceivedEventHandler dataError = new
            DataReceivedEventHandler(delegate(object sender, DataReceivedEventArgs e)
            {
                if (!string.IsNullOrEmpty(e.Data))
                    exceptionOcurred = new Exception(e.Data);
            });

            Process p1 = new Process();

            // Prepara os argumentos do comando
            string cmdArgs = "/c " + (_mysqlPath.IndexOf(' ') >= 0 ? "\"" + _mysqlPath + "\"" : _mysqlPath) + " ";

            cmdArgs += "-u " + _username + " -p" + _password + " -h " + _host +
                   " -B " + _database + 
                   " -P " + _port.ToString() + " < " +
                   (_destinationFile.IndexOf(' ') >= 0 ? "\"" + _destinationFile + "\"" : _destinationFile);

            p1.StartInfo = new ProcessStartInfo(@"cmd", cmdArgs);

            p1.EnableRaisingEvents = false;

            p1.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
            p1.StartInfo.CreateNoWindow = true;
            p1.StartInfo.RedirectStandardError = true;
            p1.StartInfo.UseShellExecute = false;

            p1.ErrorDataReceived += dataError;
            p1.Start();

            // Inicializa a leitura dos dados de erro ocorridos
            p1.BeginErrorReadLine();

            // Espera o programa ser finalizado
            p1.WaitForExit();

            p1.ErrorDataReceived -= dataError;

            // Verifica se ocorreu algum erro
            if (exceptionOcurred != null)
                throw exceptionOcurred;
        }

        #endregion
    }
}
